package com.childenglish.shiro;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.childenglish.entity.SysUser;
import com.childenglish.entity.SysRolePermission;
import com.childenglish.mapper.SysUserMapper;
import com.childenglish.mapper.SysRolePermissionMapper;
import com.childenglish.utils.PasswordEncoderUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;

    /**
     * 授权逻辑 - 支持动态权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 获取当前用户
        Object primaryPrincipal = principals.getPrimaryPrincipal();
        if (primaryPrincipal instanceof SysUser) {
            SysUser user = (SysUser) primaryPrincipal;

            // 添加用户角色
            if (user.getRole() != null) {
                authorizationInfo.addRole(user.getRole());
            }

            // 从数据库获取动态权限
            Set<String> permissions = getDynamicPermissions(user.getId());
            authorizationInfo.setStringPermissions(permissions);

            System.out.println("用户 " + user.getUsername() + " 角色: " + user.getRole() + " 权限: " + permissions);
        }

        return authorizationInfo;
    }

    /**
     * 从数据库获取用户权限
     */
    private Set<String> getDynamicPermissions(Long userId) {
        Set<String> permissions = new HashSet<>();

        try {
            // 从数据库查询用户权限
            List<SysRolePermission> rolePermissions = sysRolePermissionMapper.findByUserId(userId);

            // 转换为权限代码集合
            permissions = rolePermissions.stream()
                    .map(SysRolePermission::getPermissionCode)
                    .filter(code -> code != null && !code.trim().isEmpty())
                    .collect(Collectors.toSet());

            System.out.println("从数据库获取用户 " + userId + " 的权限: " + permissions);

        } catch (Exception e) {
            System.err.println("获取用户权限失败: " + e.getMessage());
            e.printStackTrace();
            // 如果出错，返回默认权限
            permissions.addAll(getDefaultPermissions(userId));
        }

        return permissions;
    }

    /**
     * 获取默认权限（兼容性处理）
     */
    private Set<String> getDefaultPermissions(Long userId) {
        Set<String> permissions = new HashSet<>();

        try {
            // 尝试从用户信息获取角色来设置默认权限
            SysUser user = sysUserMapper.findById(userId);
            if (user != null && user.getRole() != null) {
                switch (user.getRole()) {
                    case "admin":
                        permissions.add("system:user:view");
                        permissions.add("system:user:edit");
                        permissions.add("system:user:delete");
                        permissions.add("system:role:view");
                        permissions.add("system:role:edit");
                        permissions.add("system:role:delete");
                        permissions.add("system:permission:view");
                        permissions.add("system:permission:edit");
                        permissions.add("learning:listening:view");
                        permissions.add("learning:reading:view");
                        permissions.add("learning:game:view");
                        permissions.add("parent:child:view");
                        permissions.add("parent:progress:view");
                        permissions.add("parent:plan:edit");
                        permissions.add("teaching:class:view");
                        permissions.add("teaching:content:edit");
                        permissions.add("teaching:report:view");
                        break;
                    case "parent":
                        permissions.add("parent:child:view");
                        permissions.add("parent:progress:view");
                        permissions.add("parent:plan:edit");
                        break;
                    case "child":
                        permissions.add("learning:listening:view");
                        permissions.add("learning:reading:view");
                        permissions.add("learning:game:view");
                        break;
                    case "teacher":
                        permissions.add("teaching:class:view");
                        permissions.add("teaching:content:edit");
                        permissions.add("teaching:report:view");
                        break;
                    default:
                        // 基础学习权限
                        permissions.add("learning:listening:view");
                        permissions.add("learning:reading:view");
                        permissions.add("learning:game:view");
                        break;
                }
            } else {
                // 如果无法获取用户角色，设置最基础的权限
                permissions.add("learning:listening:view");
                permissions.add("learning:reading:view");
                permissions.add("learning:game:view");
            }
        } catch (Exception e) {
            System.err.println("获取默认权限失败: " + e.getMessage());
            // 设置最基础的权限作为最终后备
            permissions.add("learning:listening:view");
            permissions.add("learning:reading:view");
            permissions.add("learning:game:view");
        }

        System.out.println("使用默认权限: " + permissions);

        return permissions;
    }

    /**
     * 认证逻辑 - 使用BCrypt密码验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();

        // 从数据库查询用户（包含角色信息）
        SysUser user = sysUserMapper.findByUsername(username);

        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }

        // 设置BCrypt密码匹配器
        setCredentialsMatcher(new BCryptCredentialsMatcher());

        // 返回认证信息
        return new SimpleAuthenticationInfo(
                user,                    // principal - 用户信息
                user.getPassword(),      // credentials - 加密后的密码
                getName()               // realmName
        );
    }

    /**
     * BCrypt密码匹配器
     */
    private static class BCryptCredentialsMatcher implements CredentialsMatcher {
        @Override
        public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
            UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
            String rawPassword = new String(usernamePasswordToken.getPassword());
            String encodedPassword = (String) info.getCredentials();
            
            // 如果密码不是BCrypt格式，尝试兼容旧密码（用于迁移）
            if (!PasswordEncoderUtil.isBCryptFormat(encodedPassword)) {
                // 兼容旧密码：直接比较（仅用于迁移期间）
                return rawPassword.equals(encodedPassword);
            }
            
            // 使用BCrypt验证
            return PasswordEncoderUtil.matches(rawPassword, encodedPassword);
        }
    }

    /**
     * 重写方法，支持自定义token类型
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }
}